Java使用jfreechart生成pdf图表 |
您所在的位置:网站首页 › 前端生成pdf包含 echarts › Java使用jfreechart生成pdf图表 |
本项目主要技术是jfreechart和itextpdf,纯Java生成pdf图表,我给大家分享一下完成过程中遇到的各种坑.本项目适合于需要生成pdf图表又没有html模板的需求. 我尝试过freemarker,失败在模板制作上.使用word制作模板然后转成html,再使用freemarker根据html模板生成pdf,但word只能制作带表格和文本的模板,折线图这种图表只能作为图片放在模板里,这样就不能插入数据,故而失败.哪位同学知道如何制作图表模板的请不吝赐教. 还尝试过 abel533 / ECharts,我想到每次生成图表的需求可能不一样,所以想到从echarts拿到这些图表直接用,但这个我没能生成,哪位同学想试试的可以试一下 http://hzhcontrols.com/new-566194.html 还尝试过使用js的方式,找前端朋友写一个只有表格和文本的js,测试一下可以导出成pdf,然后将echarts的图表导出为js,嵌入第一个js里,再导出就发现pdf里echarts的位置是一片空白. 给大家提供一个根据html生成pdf的短小精悍的demo: import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import org.xhtmlrenderer.pdf.ITextFontResolver; import org.xhtmlrenderer.pdf.ITextRenderer; import com.lowagie.text.pdf.BaseFont; public class aaa { /** * @param args */ public static void main(String[] args) throws Exception { // Todo Auto-generated method stub String inputFile = "src/main/resources/pdfPage.html"; String url = new File(inputFile).toURI().toURL().toString(); String outputFile = "D://test.pdf"; System.out.println(url); OutputStream os = new FileOutputStream(outputFile); ITextRenderer renderer = new ITextRenderer(); renderer.setDocument(url); // 解决中文支持问题 ITextFontResolver fontResolver = renderer.getFontResolver(); fontResolver.addFont("C:/Windows/Fonts/SimsUN.TTC", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // 解决图片的相对路径问题 renderer.getSharedContext().setBaseURL("file:/D:/z/temp/"); renderer.layout(); renderer.createPDF(os); os.close(); } }最后找到了一个用无界浏览器生成的方法,相当于是在java里搭建一个浏览器,然后把页面整个画好,包括图表表格等等,然后把整个页面导出为图片,再转为pdf,整个过程很复杂,感兴趣的同学来找我要吧 正文开始~ 开始之前先放一个整体效果 首先是依赖 org.jfree jfreechart 1.5.0 com.itextpdf itext-asian 5.2.0 com.itextpdf font-asian 7.1.13 com.itextpdf itextpdf 5.5.13 com.alibaba fastjson 1.2.83 org.projectlombok lombok commons-io commons-io 2.6 org.apache.commons commons-lang3 org.apache.commons commons-collections4 4.4 org.springframework.boot spring-boot-maven-plugin然后是测试类 import com.example.util.CreatePdf; import com.example.util.Datas; import com.example.dto.TableValue; import com.itextpdf.text.DocumentException; import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @SpringBootTest class Test1ApplicationTests { @Test void GeneratePdf() throws IOException, DocumentException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); TableValue tableValue = Datas.formData(); // CreateEchartsPdfUtils.createTable(outputStream,tableContentList,tableContentList2,createLinePorts(), tableContentList3,createPiePort(),tableContentList4,createLinePort(),createBarChartsPort(),createBarChartPort(),createStackedBarChartsPort()); CreatePdf.createPdf(outputStream,tableValue); FileUtils.copyInputStreamToFile(new ByteArrayInputStream(outputStream.toByteArray()),new File("D:\\折线图/demo2.pdf")); }先来个简单表格试试水 1.表格数据源 import com.example.dto.TableValue; public class Datas { public static TableValue formData() { TableValue tableValue = new TableValue(); tableValue.setIndexValue1("1"); tableValue.setIndexValue2("2"); tableValue.setIndexValue3("3"); tableValue.setIndexValue4("4"); return tableValue; }主要框架 import com.example.dto.TableValue; import com.example.dto.ThreeLineColor; import com.itextpdf.text.*; import com.itextpdf.text.pdf.PdfWriter; import java.io.ByteArrayOutputStream; import java.io.IOException; public class CreatePdf { public static void createPdf(ByteArrayOutputStream outputStream, TableValue tableValue) throws DocumentException, IOException { // 创建一个文档(默认大小A4,边距36, 36, 36, 36) Document document = new Document(); // 设置文档大小 document.setPageSize(PageSize.A4); // 设置边距,单位都是像素,换算大约1厘米=28.33像素 document.setMargins(50, 50, 50, 50); // 创建writer,通过writer将文档写入磁盘 PdfWriter writer = PdfWriter.getInstance(document, outputStream); // 打开文档,只有打开后才能往里面加东西 document.open(); // 设置作者 document.addAuthor("作者"); // 设置创建者 document.addCreator("创建者"); //设置封面图片 Image image = Image.getInstance("src/main/resources/static/萌猫.jpg"); image.setAlignment(Image.ALIGN_LEFT); image.scaleAbsolute(500, 300); document.add(image); //设置标题 document.add(CreateEchartsPdfUtils.createHead2("生成pdf图表demo", Font.NORMAL, Element.ALIGN_CENTER)); document.add(CreateEchartsPdfUtils.createHead3("01 表格", Font.BOLD, Element.ALIGN_LEFT)); //第一个表格 oneForm(document, tableValue); document.close(); writer.close(); } /** * 文件传输量表格 * * @param * @return */ private static void oneForm(Document document, TableValue tableValue) throws DocumentException, IOException { String[] oneForm = {"抖音", "微博", "虎牙", "小红书"}; CreateEchartsPdfUtils.Form(document, tableValue, 4, oneForm, ThreeLineColor.danhui); } }多行表格的话传入list即可 输出pdf ![]() 需要注意的是,表格里的列数假如设置的是4列,数据源如果不足4个的话,整行就会不显示 2.日历图日历图其实也是表格,只不过把表格的框线全部隐藏了,并添加了不同的背景颜色 /** * 创建表格内容 * * @param table 表格对象 * @param tableContentList 表格内容对象 */ private static void createTableTwoCellCalendar(PdfPTable table, List tableContentList, BaseColor baseColor) throws DocumentException, IOException { if (ObjectUtils.isEmpty(tableContentList)) { return; } int j = 0; for (int i = 0; i < tableContentList.size(); i++) { TableValue TableValue = tableContentList.get(i); String date = TableValue.getIndexValue1(); if (StringUtils.isBlank(date)) { return; } String[] split = date.split("-"); //计算每月1号是星期几.以周四为例,返回四 int weeksOfDate = DateUtils.getWeeksOfDate(Integer.valueOf(split[0]), Integer.valueOf(split[1]), 1); //返回4 前面就空4格 返回0就不空 if (j < weeksOfDate) { table.addCell(createTableContentCalendar("", "")); j++; i--; continue; } //获取设置表格内容的字体与内容 if (i % 2 != 0) { table.addCell(createTableContentCalendar(split[2], TableValue.getIndexValue2(), TableValue.getIndexValue3(), baseColor)); } else { table.addCell(createTableContentCalendar(split[2], TableValue.getIndexValue2(), TableValue.getIndexValue3())); } } //一行内如果数据不足列数就不显示,为了让他显示,特地写了6个空字符串 table.addCell(createTableContentCalendar("", "")); table.addCell(createTableContentCalendar("", "")); table.addCell(createTableContentCalendar("", "")); table.addCell(createTableContentCalendar("", "")); table.addCell(createTableContentCalendar("", "")); table.addCell(createTableContentCalendar("", "")); } 3.折线图 /** * 生成折线图 * * @param datas 数据 * @param xName X轴 * @param yName Y轴 * @return 生成的折线图byte数组 */ public static void createLinePortImage(Document document, Map datas, String xName, String yName) throws DocumentException, IOException { try { //种类数据集 DefaultCategoryDataset dataset = new DefaultCategoryDataset(); //遍历map for (Map.Entry entry : datas.entrySet()) { String key = entry.getKey(); Map value = entry.getValue(); for (Map.Entry decimalEntry : value.entrySet()) { dataset.setValue(decimalEntry.getValue(), key, decimalEntry.getKey()); } } //创建2D折线图,折线图分水平显示和垂直显示两种 //legend:是否显示图例(对于简单的柱状图必须是false) //tooltips:是否生成工具 //urls:是否生成URL链接 JFreeChart chart = ChartFactory.createLineChart("", xName, yName, dataset, PlotOrientation.VERTICAL, true, true, true); //得到绘图区 setLineRender((CategoryPlot) chart.getPlot(), true, true); ByteArrayOutputStream bas = new ByteArrayOutputStream(); ChartUtils.writeChartAsJPEG(bas, 1.0f, chart, 800, 500, null); com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(bas.toByteArray()); image.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER); image.scaleAbsolute(500, 300); document.add(image); } catch (Exception e) { e.printStackTrace(); } } /** * 设置折线图样式 * * @param plot 折线图对象 * @param isShowDataLabels 是否显示数据标题 * @param isShapesVisible 是否显示数据点 */ public static void setLineRender(CategoryPlot plot, boolean isShowDataLabels, boolean isShapesVisible) { plot.setNoDataMessage(NO_DATA_MSG); plot.setInsets(new RectangleInsets(10, 10, 0, 10), false); LineAndShapeRenderer renderer = (LineAndShapeRenderer) plot.getRenderer(); renderer.setDefaultStroke(new BasicStroke(1.5F)); if (isShowDataLabels) { renderer.setDefaultItemLabelsVisible(true); renderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator(StandardCategoryItemLabelGenerator.DEFAULT_LABEL_FORMAT_STRING, NumberFormat.getInstance())); renderer.setDefaultPositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE1, TextAnchor.BOTTOM_CENTER)); } // 数据点绘制形状 //显示数据点 renderer.setDefaultShapesVisible(isShapesVisible); // renderer.setSeriesShapesVisible(0,isShapesVisible); //开启填充色 renderer.setUseFillPaint(isShapesVisible); //数据点填充的颜色 renderer.setSeriesFillPaint(0, Color.white); //开启外廓线(填充色开启后有效) renderer.setDrawOutlines(isShapesVisible); //使用外廓线颜色 renderer.setUseOutlinePaint(isShapesVisible); //设置外框线颜色 // renderer.setSeriesOutlinePaint(0,Color.yellow); //设置折线的颜色 renderer.setSeriesPaint(0, ThreeLineColor.sGreen); renderer.setSeriesPaint(1, ThreeLineColor.zhaxianlan); renderer.setSeriesPaint(2, ThreeLineColor.zhexianlan); //设置外廓线大小 renderer.setSeriesOutlineStroke(0, new BasicStroke(2.0F)); //设置线条粗细(setDefaultStroke和这个方法冲突) renderer.setSeriesStroke(0, new BasicStroke(1.0F)); //圆形数据点 // renderer.setSeriesShape(0, new Ellipse2D.Double(-2.0D,-2.0D,5.0D,5.0D) ); plot.setRenderer(renderer); setXAixs(plot, CategoryLabelPositions.STANDARD); setYAixs(plot); }x轴和y轴的设置 /** * 设置类别图表(CategoryPlot) X坐标轴线条颜色和样式 * * @param plot 类别图表对象 categoryLabelPositions x轴文字倾斜度 */ public static void setXAixs(CategoryPlot plot, CategoryLabelPositions categoryLabelPositions) { Color lineColor = new Color(51, 51, 51); //STANDARD:x轴的字体倾斜度 CategoryAxis axis = plot.getDomainAxis(); axis.setCategoryLabelPositions(categoryLabelPositions); // X坐标轴颜色 axis.setAxisLinePaint(lineColor); // X坐标轴标记|竖线颜色 axis.setTickMarkPaint(lineColor); axis.setLabelFont(FONT); // font = Font.createFont(Font.TRUETYPE_FONT,new FileInputStream("/usr/share/fonts/cjkuni-uming/uming.ttc")); axis.setTickLabelFont(FONT); } /** * 设置类别图表(CategoryPlot) Y坐标轴线条颜色和样式 同时防止数据无法显示 * * @param plot 类别图表对象 */ public static void setYAixs(CategoryPlot plot) { Color axisColor = new Color(51, 51, 51); Color tickColor = new Color(219, 218, 218); ValueAxis axis = plot.getRangeAxis(); // Y坐标轴颜色 axis.setAxisLinePaint(axisColor); // Y坐标轴标记|竖线颜色 axis.setTickMarkPaint(tickColor); // false隐藏Y刻度 axis.setAxisLineVisible(true); axis.setTickMarksVisible(true); // Y轴网格线条 plot.setRangeGridlinePaint(new Color(229, 229, 229)); plot.setRangeGridlineStroke(new BasicStroke(1)); // 设置顶部Y坐标轴间距,防止数据无法显示 axis.setUpperMargin(0.1); // 设置底部Y坐标轴间距 axis.setLowerMargin(0.1); axis.setLabelFont(FONT); axis.setTickLabelFont(FONT); //设置y最小取值范围.如果数据全是0,那么0这条折线将显示在y轴中间,y轴0刻度以下将用负数表示, // 但是是显示的是 0E0,-1E-9,-2E-9,-3E-9,-4E-9,这样用科学计数法表示的数,加上这个可 // 以让y轴在数据为0的时候折线在0的水平位置,接近于x轴.但是y轴刻度仍任是科学计数法.不介意的话可以用 //还可以设置最大值,这样的话y轴刻度就不会自动生成了,就是0-1000 /* axis.setLowerBound(0); axis.setUpperBound(1000);*/ }效果是这样子 ![]() 大家有没有发现,x轴的字怎么模糊不清呢?是不是字体太小了呢? ![]() 放大也是这样,这事因为x轴的内容是 2023-01-01这样的日期,太长了. 将 setLineRender方法末尾的setXAixs(plot, CategoryLabelPositions.STANDARD)修改为CategoryLabelPositions.UP_45,将字体倾斜45度,效果如下 ![]() 折线和数据点的颜色,数据点的形状等等都是可以自由调节的. 4.饼状图 /** * 生成饼图 * * @param datas 数据 * @return 返回生成的byte数组 */ public static void createPiePortImage(Document document, Map datas) throws DocumentException, IOException { try { // 如果不使用Font,中文将显示不出来 DefaultPieDataset pds = new DefaultPieDataset(); //遍历map for (Map.Entry entry : datas.entrySet()) { pds.setValue(entry.getKey(), entry.getValue()); } /** * 生成一个饼图的图表 * 分别是:显示图表的标题、需要提供对应图表的DateSet对象、是否显示图例、是否生成贴士以及是否生成URL链接 */ JFreeChart chart = ChartFactory.createPieChart("", pds, true, true, true); setPieRender(chart.getPlot()); ByteArrayOutputStream bas = new ByteArrayOutputStream(); ChartUtils.writeChartAsJPEG(bas, 1.0f, chart, 800, 500, null); com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(bas.toByteArray()); image.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER); image.scaleAbsolute(500, 300); document.add(image); } catch (Exception e) { e.printStackTrace(); } } /** * 设置饼状图渲染 * * @param plot 饼图对象 */ public static void setPieRender(Plot plot) { plot.setNoDataMessage(NO_DATA_MSG); plot.setInsets(new RectangleInsets(10, 10, 5, 10)); PiePlot piePlot = (PiePlot) plot; piePlot.setInsets(new RectangleInsets(0, 0, 0, 0)); // 圆形 piePlot.setCircular(true); piePlot.setLabelGap(0.01); piePlot.setInteriorGap(0.05D); // 图例形状 piePlot.setLegendItemShape(new Rectangle(10, 10)); piePlot.setIgnoreNullValues(true); // 去掉背景色 piePlot.setLabelBackgroundPaint(null); // 去掉阴影 piePlot.setLabelShadowPaint(null); // 去掉边框 piePlot.setLabelOutlinePaint(null); piePlot.setShadowPaint(null); // 0:category 1:value:2 :percentage // 显示标签数据 {0} 代表 饼状图分类的名字,{1} 显示具体数值,{2} 显示百分比 //{0}:{1} 英雄联盟:20 {0}:{2} 英雄联盟 20% piePlot.setLabelGenerator(new StandardPieSectionLabelGenerator("{0}:{1}")); }饼状图挺简单的,需要注意的就是值的显示 {0}:{1}显示的就是 ![]() {0}:{2}显示的就是百分比 柱状图 /** * 生成柱状图 * * @param datas 数据 * @return */ public static void createBarChartImage(Document document, Map datas) throws DocumentException, IOException { try { //种类数据集 DefaultCategoryDataset dataset = new DefaultCategoryDataset(); //遍历map for (Map.Entry entry : datas.entrySet()) { String key = entry.getKey(); Map value = entry.getValue(); for (Map.Entry decimalEntry : value.entrySet()) { dataset.setValue(decimalEntry.getValue(), key, decimalEntry.getKey()); } } //legend:是否显示图例(对于简单的柱状图必须是false) //tooltips:是否生成工具 //urls:是否生成URL链接 JFreeChart chart = ChartFactory.createBarChart("", "", "", dataset, PlotOrientation.VERTICAL, true, true, false); //得到绘图区 setBarChartRender((CategoryPlot) chart.getPlot(), true, true); ByteArrayOutputStream bas = new ByteArrayOutputStream(); ChartUtils.writeChartAsJPEG(bas, 1.0f, chart, 800, 500, null); com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(bas.toByteArray()); image.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER); image.scaleAbsolute(500, 300); document.add(image); } catch (Exception e) { e.printStackTrace(); } } /** * 设置柱状图样式 * * @param plot 折线图对象 * @param isShowDataLabels 是否显示数据标题 * @param isShapesVisible 是否显示数据点 */ public static void setBarChartRender(CategoryPlot plot, boolean isShowDataLabels, boolean isShapesVisible) { plot.setNoDataMessage(NO_DATA_MSG); plot.setInsets(new RectangleInsets(10, 10, 0, 10), false); BarRenderer renderer = (BarRenderer) plot.getRenderer(); renderer.setDefaultStroke(new BasicStroke(0F)); if (isShowDataLabels) { renderer.setDefaultItemLabelsVisible(true); renderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator(StandardCategoryItemLabelGenerator.DEFAULT_LABEL_FORMAT_STRING, NumberFormat.getInstance())); renderer.setDefaultPositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE12, TextAnchor.BASELINE_CENTER)); } renderer.setDefaultSeriesVisible(true); //设置柱子的宽度 renderer.setMaximumBarWidth(0.05); //设置柱子的高度 // renderer.setMinimumBarLength(0.2); //设置柱子边框线可见 // renderer.setDrawBarOutline(isShapesVisible); //设置柱子边框线的颜色 // renderer.setSeriesOutlinePaint(0, Color.green); //设置每个地区所包含的平行柱的距离 // renderer.setItemMargin(0.5); //显示每个柱的数值,并修改该数值的字体属性 renderer.setIncludeBaseInRange(true); //柱子的透明度 plot.setForegroundAlpha(1.0f); //柱子的文字偏离值 // renderer.setItemLabelAnchorOffset(10D); //设置柱子的颜色 renderer.setSeriesPaint(0, Color.yellow); //设置外廓线大小 /* renderer.setSeriesOutlineStroke(0,new BasicStroke(2.0F)); //设置线条粗细 renderer.setSeriesStroke(0,new BasicStroke(2.0F));*/ setXAixs(plot, CategoryLabelPositions.STANDARD); setYAixs(plot); }柱子的颜色,透明度,都是可以设置的,字体也可以设置为柱体内,柱体上,柱体旁 ![]() 只需将ChartFactory的createBarChart改为createStackedBarChart就可以 7.柱状图和折线图的组合图第一种是y轴分离,相当于两个图合在一起,共享x轴 ![]() 第二种是双y轴,折线图和柱状图有交互的组合图 ![]() 更多组合形式请前往https://yveshe.blog.csdn.net/article/details/81560666?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-4-81560666-blog-91975252.pc_relevant_recovery_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-4-81560666-blog-91975252.pc_relevant_recovery_v2&utm_relevant_index=4 有这种的 ![]() ![]() ![]() ![]() tips1 每一个图表,我都是先写标题,再画图表 document.add(CreateEchartsPdfUtils.createHead3("01 表格", Font.BOLD, Element.ALIGN_LEFT)); //第一个表格 oneForm(document, tableValue); //日历图 document.add(CreateEchartsPdfUtils.createHead3("02 日历图", Font.BOLD, Element.ALIGN_LEFT)); CreateEchartsPdfUtils.calendarTwoForm(document, calendar); //折线图 document.add(CreateEchartsPdfUtils.createHead3("03 折线图", Font.BOLD, Element.ALIGN_LEFT)); JFreeChartUtils.createLinePortImage(document, linePorts, "日期", "数量"); //饼状图 document.add(CreateEchartsPdfUtils.createHead3("04 饼状图", Font.BOLD, Element.ALIGN_LEFT)); JFreeChartUtils.createPiePortImage(document, piePort); //柱状图 document.add(CreateEchartsPdfUtils.createHead3("05 柱状图", Font.BOLD, Element.ALIGN_LEFT)); JFreeChartUtils.createBarChartImage(document, barChartPort); //堆叠柱状图 document.add(CreateEchartsPdfUtils.createHead3("06 堆叠柱状图", Font.BOLD, Element.ALIGN_LEFT)); JFreeChartUtils.createStackedBarChart(document, stackedBarChartsPort); //柱状图和折线图组合图1 document.add(CreateEchartsPdfUtils.createHead3("07 柱状图和折线图组合图1", Font.BOLD, Element.ALIGN_LEFT)); JFreeChartUtils.createBarChartAndLineImage(document, linePorts); //柱状图和折线图组合图2 双y轴 document.add(CreateEchartsPdfUtils.createHead3("08 柱状图和折线图组合图2", Font.BOLD, Element.ALIGN_LEFT)); JFreeChartUtils.createChart(document, linePorts);但是实际结果可能是这样的 ![]() 这可能是jfreechart为了节省空间自动做的排版,遇到这样的情况大家可以先开发,开发完成后统一处理,可以在柱状图代码后加上document.newPage(); ![]() tips2 上linux测试环境进行测试后,遇到一个关于字体的问题 private static Font createFont(int fontSize, int fontMode, BaseColor fontColor) throws DocumentException, IOException { BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); return new Font(bfChinese, fontSize, fontMode, fontColor); }这是创建标题时createHead3 所用的,Font是itext下的包,测试环境可以正常创建标题,正常显示 而折线图的x轴所用的字体是awt的字体 private static final Font FONT = new Font("STSongStd-Light", Font.BOLD, 12);awt的字体在测试环境找不到,所以自动找了个默认字体,贼丑,而且不清晰. 和itext的font相比,awt的font没有编码方式 只找到了itext的字体转awt字体的方法,没有找到awt转itext的方法 试过直接写字体文件名,写字体绝对路径,将字体转成流,都不行.最后将时间由2023-01-02格式改为日期 02,CategoryLabelPositions.UP_45修改为STANDARD,勉强再用.如果有懂的大佬指导下我应该怎么解决,如果你也遇到这个问题不知道怎么解决的话可以用我这个方法 tips3 大家生成pdf肯定都是调用好几个接口,等候接口返回数据再调下一个接口,整体响应时间太长,可以用CompletableFuture进行异步调用 原来取数据: @Test void GeneratePdf() throws IOException, DocumentException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); TableValue tableValue = Datas.formData(); List calendar = Datas.calendar(); Map linePorts = Datas.createLinePorts(); Map piePort = Datas.createPiePort(); Map barChartPort = Datas.createBarChartPort(); Map stackedBarChartsPort = Datas.createStackedBarChartsPort(); // CreateEchartsPdfUtils.createTable(outputStream,tableContentList,tableContentList2,createLinePorts(), tableContentList3,createPiePort(),tableContentList4,createLinePort(),createBarChartsPort(),createBarChartPort(),createStackedBarChartsPort()); CreatePdf.createPdf(outputStream,tableValue,calendar,linePorts,piePort,barChartPort,stackedBarChartsPort); FileUtils.copyInputStreamToFile(new ByteArrayInputStream(outputStream.toByteArray()),new File("D:\\折线图/demo2.pdf")); }使用CompletableFuture以后 @Test void GeneratePdf() throws IOException, DocumentException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); // TableValue tableValue = Datas.formData(); CompletableFuture tableValue = CompletableFuture.supplyAsync(() -> Datas.formData()); // List calendar = Datas.calendar(); CompletableFuture calendar = CompletableFuture.supplyAsync(() -> Datas.calendar()); // Map linePorts = Datas.createLinePorts(); CompletableFuture linePorts = CompletableFuture.supplyAsync(() -> Datas.createLinePorts()); // Map piePort = Datas.createPiePort(); CompletableFuture piePort = CompletableFuture.supplyAsync(() -> Datas.createPiePort()); // Map barChartPort = Datas.createBarChartPort(); CompletableFuture barChartPort = CompletableFuture.supplyAsync(() -> Datas.createBarChartPort()); // Map stackedBarChartsPort = Datas.createStackedBarChartsPort(); CompletableFuture stackedBarChartsPort = CompletableFuture.supplyAsync(() -> Datas.createStackedBarChartsPort()); CompletableFuture.allOf(tableValue,calendar,linePorts,piePort,barChartPort,stackedBarChartsPort); // CreateEchartsPdfUtils.createTable(outputStream,tableContentList,tableContentList2,createLinePorts(), tableContentList3,createPiePort(),tableContentList4,createLinePort(),createBarChartsPort(),createBarChartPort(),createStackedBarChartsPort()); CreatePdf.createPdf(outputStream,tableValue.join(),calendar.join(),linePorts.join(),piePort.join(),barChartPort.join(),stackedBarChartsPort.join()); FileUtils.copyInputStreamToFile(new ByteArrayInputStream(outputStream.toByteArray()),new File("D:\\折线图/demo2.pdf")); }tips4 以上都是直接将文件在本地生成,实际使用中需要前端发送请求,我们将文件流给前端返回,该怎么做呢 public void generateEDBPdf(HttpServletResponse response) throws IOException { String name = "要定义的文件名称"; response.setHeader("Content-Disposition", "attachment;filename=" + name + ".pdf"); response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); response.setContentType("application/pdf;charset=UTF-8"); ServletOutputStream output = response.getOutputStream(); BufferedOutputStream outputStream = new BufferedOutputStream(output); // CreatePdf.createPdf(outputStream,tableValue.join(),calendar.join(),linePorts.join(),piePort.join(),barChartPort.join(),stackedBarChartsPort.join()); }将CreatePdf.createPdf这个方法里的outputStream改为这个controller对应的Stream就好了 项目git地址 :https://gitee.com/mhjo/minghe/tree/jfree/ 大家想推代码请新建分支~ 原文链接:https://blog.csdn.net/lol19950605/article/details/128929870 |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |